﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using Microsoft.Services.Clab.UI.Mvvmc.Presentation.Properties;

namespace Microsoft.Services.Clab.UI.Mvvmc.Presentation
{
    public class PropertySyncHelper
    {
        public List<PropertySync> PropertyMappings { get; private set; }

        public PropertySyncHelper()
        {
            this.PropertyMappings = new List<PropertySync>();
        }

        public void UpdateAllViewModelProperties(IView source, IPropertyAccessor target)
        {
            foreach (var mapping in this.PropertyMappings)
            {
#if (!SILVERLIGHT)
                if (mapping.ViewDependencyProperty.IsAlive && mapping.ViewDependencyProperty.GetReference<DependencyProperty>().OwnerType.Equals(source.GetType()))
#else
                if (mapping.ViewDependencyProperty.IsAlive)
#endif
                {
                    UpdateViewModelProperty(source, mapping.ViewDependencyProperty.GetReference<DependencyProperty>(), target);
                }
            }
        }

        public void UpdateViewModelProperty(IView source, DependencyProperty sourceProperty, IPropertyAccessor target)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (sourceProperty == null)
            {
                throw new ArgumentNullException("sourceProperty");
            }

            if (target == null)
            {
                throw new ArgumentNullException("target");
            }

            var wpfSource = source as DependencyObject;
            if (wpfSource == null)
            {
                throw new ArgumentException(Resources.SourceMustBeDependencyObject, "source");
            }

            var mapping = this.PropertyMappings.SingleOrDefault(p => p.ViewDependencyProperty.GetReference<DependencyProperty>() == sourceProperty);
            if (mapping != null && !mapping.IsUpdating)
            {
                using (var l = mapping.LockUpdate())
                {
                    if (l.Acquired)
                    {
                        var value = wpfSource.GetValue(mapping.ViewDependencyProperty.GetReference<DependencyProperty>());
                        target.SetValue(mapping.ViewModelPropertyName, value);
                    }
                }
            }
        }

        public void UpdateViewDependencyProperty(IPropertyAccessor source, string sourceProperty, ViewCollection targetCollection)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (string.IsNullOrEmpty(sourceProperty))
            {
                throw new ArgumentNullException("sourceProperty");
            }

            if (targetCollection == null)
            {
                throw new ArgumentNullException("target");
            }


            var mapping = this.PropertyMappings.SingleOrDefault(p => p.ViewModelPropertyName == sourceProperty);
            if (mapping != null && !mapping.IsUpdating && mapping.ViewDependencyProperty.IsAlive)
            {
                foreach (IView target in targetCollection)
                {
                    var wpfTarget = target as DependencyObject;

#if !SILVERLIGHT
                    if (wpfTarget != null && wpfTarget.GetType().Equals(mapping.ViewDependencyProperty.GetReference<DependencyProperty>().OwnerType))
#else
                    if (wpfTarget != null)
#endif
                    {
                        using (var l = mapping.LockUpdate())
                        {
                            if (l.Acquired)
                            {
                                var value = source.GetValue(mapping.ViewModelPropertyName);
                                wpfTarget.SetValue(mapping.ViewDependencyProperty.GetReference<DependencyProperty>(), value);
                            }
                        }
                    }
                }
            }
        }
    }
}
